
//package java_cup.runtime;

//import java.util.Stack;

/**
 * This class : a temporary or "virtual" parse stack that replaces the
 * Peek portion of the actual parse stack (the part that has been changed by some
 * set of operations) while maintaining its original contents. This data
 * structure is used when the parse needs to "parse ahead" to determine if a
 * given error recovery attempt will allow the parse to continue far enough to
 * consider it successful. Once success or failure of parse ahead is determined
 * the system then reverts to the original parse stack (which has not actually
 * been modified). Since parse ahead does not execute actions, only parse state
 * is maintained on the virtual stack, not full TheSymbolDraft objects.
 *
 * @see java_cup.runtime.LRParser
 * @version last updated: 7/3/96
 * @author Frank Flannery
 */

public class VirtualParseStack {
    /*-----------------------------------------------------------*/
    /*--- Constructor(s) ----------------------------------------*/
    /*-----------------------------------------------------------*/

    /** Constructor to build a virtual stack @out of a real stack. */
    public VirtualParseStack(Stack<Node> shadowingStack) /*throws java.lang.ExceptionXml*/ {
        /* sanity check */
        if (shadowingStack == null)
            throw new Exception("Internal CUPParser error: attempt to create null virtual stack");

        /* set up our internals */
        real_stack = shadowingStack;
        _vstack = new();
        real_next = 0;

        /* get one element onto the virtual portion of the stack */
        getFromReal();
    }

    /*-----------------------------------------------------------*/
    /*--- (Access to) Instance Variables ------------------------*/
    /*-----------------------------------------------------------*/

    /**
     * The real stack that we shadow. This is accessed when we move off the bottom
     * of the virtual portion of the stack, but is always _left unmodified.
     */
    public Stack<Node> real_stack;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /**
     * Top of stack indicator for where we leave off in the real stack. This is
     * measured from Peek of stack, so 0 would indicate that no elements have been
     * "moved" from the real to virtual stack.
     */
    public int real_next;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /**
     * The virtual Peek portion of the stack. This stack contains int? objects
     * with state numbers. This stack shadows the Peek portion of the real stack
     * within the area that has been modified (via operations on the virtual stack).
     * When this portion of the stack becomes empty we transfer elements from the
     * underlying stack onto this stack.
     */
    public Stack<int> _vstack;

    /*-----------------------------------------------------------*/
    /*--- General Methods ---------------------------------------*/
    /*-----------------------------------------------------------*/

    /**
     * Transfer an element from the real to the virtual stack. This assumes that the
     * virtual stack is currently empty.
     */
    public void getFromReal() {
        Node stack_sym;

        /* don't transfer if the real stack is empty */
        if (real_next >= real_stack.Count)
            return;

        /* get a copy of the first TheSymbolDraft we have not transfered */
        stack_sym = real_stack.ElementAt(real_stack.Count - 1 - real_next);

        /* record the transfer */
        real_next++;

        /* put the state Count from the TheSymbolDraft onto the virtual stack */
        _vstack.Push(stack_sym.parse_state);
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Indicate whether the stack is empty. */
    public bool empty =>
        /*
* if _vstack is empty then we were unable to transfer onto it and the whole
* thing is empty.
*/
        _vstack.Count == 0;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Return value on the Peek of the stack (without popping it). */
    public int Peek() /*throws java.lang.ExceptionXml*/ {
        if (_vstack.Count == 0)
            throw new Exception("Internal CUPParser error: Peek() called on empty virtual stack");

        return _vstack.Peek();
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Pop the stack. */
    public void Pop() /*throws java.lang.ExceptionXml*/ {
        if (_vstack.Count == 0)
            throw new Exception("Internal CUPParser error: Pop from empty virtual stack");

        /* Pop it */
        _vstack.Pop();

        /* if we are now empty transfer an element (if there is one) */
        if (_vstack.Count == 0)
            getFromReal();
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Push a state Count onto the stack. */
    public void Push(int stateNum) {
        _vstack.Push(stateNum);
    }

    /*-----------------------------------------------------------*/

}
